from flask import Flask
from flask import session
from flask_sqlalchemy import SQLAlchemy
from redis import StrictRedis
from flask_session import Session
from datetime import timedelta
from flask_wtf.csrf import CSRFProtect, generate_csrf
from config import Dict    # 导入管理环境的容器
# from info.modules.index import index_blue
# 导入info里的modules里的index里的蓝图对象

import logging     # 导入日志信息模块
from logging.handlers import RotatingFileHandler



# 为了让其他模块可以使用redis_store
redis_store = None
# 产生问题: 循环导包--解决办法,断掉其中一环就好  将index_blue导入放到需要使用到它的代码上面

db = SQLAlchemy()


# 入口方法/工厂方法
def create_app(config_name):

    # 判断传入的参数是否在容器中合法
    if config_name not in Dict:   # 不存在 Dict里面
        raise Exception('传递的参数有误')

    app = Flask(__name__)

    # config = Dict['develop']
    config = Dict[config_name]

    log_file(config.LEVEL)  # 调用日志函数里的方法

    # 加载配置信息到app中
    app.config.from_object(config)

    # 创建SQLAlchemy,关联app
    # db = SQLAlchemy(app)   # 将这句话分成两句话 db=SQLAlchemy() 放在上面
    db.init_app(app)
    # 创建redis对象
    global redis_store  # 将redis_store 声明为全局变量修改 不再为None
    redis_store = StrictRedis(host=config.REDIS_HOST, port=config.REDIS_PORT, decode_responses=True)  # decode_responses=True, 可以自动解码成字符串

    # 创建Session对象 读取app中的session 信息
    Session(app)

    # 创建CSRFProtect 保护app  保护四种访问方式 不会保护GET
    # POST PUT PATCH DELETE
    CSRFProtect(app)

    # 注册首页蓝图到app中
    from info.modules.index import index_blue
    app.register_blueprint(index_blue)

    # 注册认证蓝图到app中
    from info.modules.passport import passport_blue
    app.register_blueprint(passport_blue)

    # 注册新闻蓝图到app中
    from info.modules.news import news_bilue
    app.register_blueprint(news_bilue)

    # 注册用户个人信息蓝图到app中
    from info.modules.profiles import profile_biue
    app.register_blueprint(profile_biue)

    # 使用请求钩子拦截所有的请求
    # 每个请求的时候好,都向cookie中写入一个csrf_token, 通过请求钩子after_request拦截设置csrf_token
    @app.after_request
    def set_csrf_token(response):
        # 使用after_request请求钩子装饰时,每个请求都会触发执行这里的代码
        csrf_token = generate_csrf()
        # 调用generate_csrf方法就会生成一个csrf_token
        response.set_cookie("csrf_token", csrf_token)
        return response
        # 返回响应

    # 使用自定义过滤器,参数一:函数名字, 参数二:过滤器名字
    from info.utils.commons import index_class
    app.add_template_filter(index_class, 'index_class')

    print(app.url_map)
    return app


# 使用方法 然后创建一个文件夹logs,  就会把日志记录在logs
# 可以使用logging 模块  也可以使用current_app.logger都可以
def log_file(LEVEL):
    # 设置日志的记录等级
    logging.basicConfig(level=LEVEL)  # 调试debug级

    # 创建日志记录器,指明日志保存的路径,每个日志的最大容量,保存的日志文件个数上限
    file_log_handler = RotatingFileHandler('logs/log', maxBytes=1024 * 1024 * 100, backupCount=10)

    # 创建日志记录的格式,日志等级,输入日志信息的文件名,行数,日志信息
    formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')

    # 为刚创建的日志记录器设置日志记录格式
    file_log_handler.setFormatter(formatter)

    # 为全局的日志工具对象(flask app 使用的)添加日志记录器
    logging.getLogger().addHandler(file_log_handler)